package top.jacktgq.itheima.netty.protocol_design.groupchat.rpc;

import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import lombok.extern.slf4j.Slf4j;
import top.jacktgq.itheima.netty.protocol_design.groupchat.message.RpcRequestMessage;
import top.jacktgq.itheima.netty.protocol_design.groupchat.message.RpcResponseMessage;
import top.jacktgq.itheima.netty.protocol_design.groupchat.server.service.HelloService;
import top.jacktgq.itheima.netty.protocol_design.groupchat.server.service.ServicesFactory;

import java.lang.reflect.Method;

/**
 * @Author CandyWall
 * @Date 2021/3/25--16:18
 * @Description
 */
@Slf4j
@ChannelHandler.Sharable
public class RpcRequestMessageHandler extends SimpleChannelInboundHandler<RpcRequestMessage> {
    @Override
    protected void channelRead0(ChannelHandlerContext ctx, RpcRequestMessage msg) {
        RpcResponseMessage rpcResponseMessage = new RpcResponseMessage();
        rpcResponseMessage.setSequenceId(msg.getSequenceId());
        try {
            HelloService service = (HelloService) ServicesFactory.getService(Class.forName(msg.getInterfaceName()));
            Method method = service.getClass().getMethod(msg.getMethodName(), msg.getParameterTypes());
            Object result = method.invoke(service, msg.getParameterValue());
            rpcResponseMessage.setReturnValue(result);
        } catch (Exception e) {
            // e.printStackTrace();
            // 这里不能直接将异常信息全部发送给客户端，由于有些异常信息序列化之后会有上万字节
            // 客户端往往对一次发送的字节数做了限制，会报超出最大发送的字节数的异常，
            // 而且没有必要一次性发那么长的异常信息过去，这里只发送方法调用的源头异常信息
            rpcResponseMessage.setErrorMsg("远程调用出错：" + ExceptionUtil.getRealMessage(e));
        }
        ctx.writeAndFlush(rpcResponseMessage);
    }

    /*public static void main(String[] args) throws Exception {
        RpcRequestMessage message = new RpcRequestMessage(
          1,
          "top.jacktgq.itheima.netty.protocol_design.groupchat.server.service.HelloService",
          "sayHello",
          String.class,
          new Class[] {String.class},
          new Object[]{"张三"}
        );
        HelloService service = (HelloService) ServicesFactory.getService(Class.forName(message.getInterfaceName()));
        Method method = service.getClass().getMethod(message.getMethodName(), message.getParameterTypes());
        Object result = method.invoke(service, message.getParameterValue());
    }*/
}
